package com.tsfyun.scm.service.impl.logistics;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.logistics.DomesticLogisticsDTO;
import com.tsfyun.scm.entity.customer.SupplierTakeInfo;
import com.tsfyun.scm.entity.logistics.DomesticLogistics;
import com.tsfyun.scm.mapper.logistics.DomesticLogisticsMapper;
import com.tsfyun.scm.service.logistics.IDomesticLogisticsService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.logistics.DomesticLogisticsVO;
import com.tsfyun.scm.vo.logistics.SimpleDomesticLogisticsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * <p>
 * 国内物流 服务实现类
 * </p>
 *

 * @since 2020-03-25
 */
@Service
public class DomesticLogisticsServiceImpl extends ServiceImpl<DomesticLogistics> implements IDomesticLogisticsService {

    @Autowired
    private DomesticLogisticsMapper domesticLogisticsMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(DomesticLogisticsDTO dto) {
        DomesticLogistics domesticLogistics = new DomesticLogistics();
        domesticLogistics.setCode(dto.getCode());
        domesticLogistics.setName(dto.getName());
        domesticLogistics.setLocking(Boolean.FALSE);
        domesticLogistics.setDisabled(Boolean.FALSE);
        if(CollUtil.isNotEmpty(dto.getTimeliness())) {
            //增加长度验证，防止引用的地方数据库无法保存
            IntStream.range(0,dto.getTimeliness().size()).forEach(idx->{
                String timeline = dto.getTimeliness().get(idx);
                TsfPreconditions.checkArgument(timeline.length() <= 50,new ServiceException("时效长度不能大于50位"));
                TsfPreconditions.checkArgument(!timeline.contains(","),new ServiceException("时效包含非法字符"));
            });
            //去重
            domesticLogistics.setTimeliness(String.join(",", dto.getTimeliness().stream().distinct().collect(Collectors.toList())));
        }
        try {
            super.saveNonNull(domesticLogistics);
        } catch (DuplicateKeyException e) {
            if(e.getMessage().contains("uni_code")) {
                throw new ServiceException("编码已经存在");
            } else if (e.getMessage().contains("uni_name")) {
                throw new ServiceException("名称已经存在");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(DomesticLogisticsDTO dto) {
        DomesticLogistics domesticLogistics =  super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(domesticLogistics),new ServiceException("数据不存在"));
        //锁定的不允许修改
        TsfPreconditions.checkArgument(Objects.equals(domesticLogistics.getLocking(),Boolean.FALSE),new ServiceException("数据已被锁定，不允许操作"));
        domesticLogistics.setCode(dto.getCode());
        domesticLogistics.setName(dto.getName());
        if(CollUtil.isNotEmpty(dto.getTimeliness())) {
            //增加长度验证，防止引用的地方数据库无法保存
            IntStream.range(0,dto.getTimeliness().size()).forEach(idx->{
                String timeline = dto.getTimeliness().get(idx);
                TsfPreconditions.checkArgument(timeline.length() <= 50,new ServiceException("时效长度不能大于50位"));
                TsfPreconditions.checkArgument(!timeline.contains(","),new ServiceException("时效包含非法字符"));
            });
            //去重
            domesticLogistics.setTimeliness(String.join(",", dto.getTimeliness().stream().distinct().collect(Collectors.toList())));
        }
        try {
            super.updateById(domesticLogistics);
        } catch (DuplicateKeyException e) {
            if(e.getMessage().contains("uni_code")) {
                throw new ServiceException("编码已经存在");
            } else if (e.getMessage().contains("uni_name")) {
                throw new ServiceException("名称已经存在");
            }
        }
    }

    @Override
    public PageInfo<DomesticLogisticsVO> pageList(DomesticLogisticsDTO dto) {
        PageHelper.startPage(dto.getPage(),dto.getLimit());
        List<DomesticLogisticsVO> dataList =  domesticLogisticsMapper.list(dto);
        if(CollUtil.isNotEmpty(dataList)) {
            dataList.stream().forEach(r->{
                r.setTimeline(Arrays.asList(org.springframework.util.StringUtils.commaDelimitedListToStringArray(r.getTimeliness())));
            });
        }
        return new PageInfo<>(dataList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        DomesticLogistics domesticLogistics =  super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(domesticLogistics),new ServiceException("数据不存在"));
        //锁定的不允许删除
        TsfPreconditions.checkArgument(Objects.equals(domesticLogistics.getLocking(),Boolean.FALSE),new ServiceException("数据已被锁定，不允许操作"));
        try {
            super.removeById(id);
            //以防万一有级联
        } catch (DataIntegrityViolationException e) {
            throw new ServiceException("当前数据存在关联性数据，不允许删除");
        }
    }

    @Override
    public List<SimpleDomesticLogisticsVO> select() {
        List<SimpleDomesticLogisticsVO> dataList = Lists.newArrayList();
        DomesticLogistics condition = new DomesticLogistics();
        condition.setDisabled(Boolean.FALSE);
        List<DomesticLogistics> domesticLogisticss = domesticLogisticsMapper.select(condition);
        //时效要求逗号隔开处理
        SimpleDomesticLogisticsVO domesticLogisticsVO = null;
        if(!CollectionUtils.isEmpty(domesticLogisticss)) {
            domesticLogisticss = domesticLogisticss.stream().sorted(Comparator.comparing(DomesticLogistics::getDateUpdated).reversed()).collect(Collectors.toList());

            for(DomesticLogistics dl : domesticLogisticss) {
                domesticLogisticsVO = new SimpleDomesticLogisticsVO();
                domesticLogisticsVO.setId(dl.getId());
                domesticLogisticsVO.setCode(dl.getCode());
                domesticLogisticsVO.setName(dl.getName());
                //此处修正，如果只有一项则没有逗号分隔
                domesticLogisticsVO.setTimeline(StringUtils.isNotEmpty(dl.getTimeliness()) ? Arrays.asList(dl.getTimeliness().split(",")) : null);
                dataList.add(domesticLogisticsVO);
            }
        }
        return dataList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        DomesticLogistics domesticLogistics =  super.getById(id);
        Optional.ofNullable(domesticLogistics).orElseThrow(()->new ServiceException("数据不存在"));
        DomesticLogistics update = new DomesticLogistics();
        update.setDisabled(disabled);
        domesticLogisticsMapper.updateByExampleSelective(update, Example.builder(DomesticLogistics.class).where(
                TsfWeekendSqls.<DomesticLogistics>custom().andEqualTo(false,DomesticLogistics::getId,id)
        ).build());
    }

    @Override
    public DomesticLogisticsVO detail(Long id) {
        DomesticLogistics domesticLogistics =  super.getById(id);
        Optional.ofNullable(domesticLogistics).orElseThrow(()->new ServiceException("数据不存在"));
        DomesticLogisticsVO domesticLogisticsVO = new DomesticLogisticsVO();
        domesticLogisticsVO.setId(id);
        domesticLogisticsVO.setCode(domesticLogistics.getCode());
        domesticLogisticsVO.setName(domesticLogistics.getName());
        domesticLogisticsVO.setDisabled(domesticLogistics.getDisabled());
        domesticLogisticsVO.setLocking(domesticLogistics.getLocking());
        domesticLogisticsVO.setTimeline(Arrays.asList(org.springframework.util.StringUtils.commaDelimitedListToStringArray(domesticLogistics.getTimeliness())));
        return domesticLogisticsVO;
    }
}
